#define progma once
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include "Sem.hpp"
#include "Mutex.hpp"
using namespace std;

const int g_default_ringqueue_capacity = 6;
template <typename T>
class RingQueue
{
public:
    RingQueue(int capacity = g_default_ringqueue_capacity)
        : _rq(capacity), _capacity(capacity), _blank_sem(capacity), _p_step(0), _data_sem(0), _c_step(0)
    {
    }
    void EnQueue(const T &input)
    {

        _blank_sem.P();
        {
            MutexGuard mutex(_p_mutex); // RAII模式
            _rq[_p_step++] = input;
            _p_step %= _capacity;
        }
        _data_sem.V();
    }
    void Pop(T *output)
    {
        _data_sem.P();
        {
            MutexGuard mutex(_p_mutex); // RAII模式
            *output = _rq[_c_step++];
            _c_step %= _capacity;
        }
        _blank_sem.V();
    }

private:
    vector<T> _rq;
    int _capacity;
    // 生产者
    Sem _blank_sem; // 空位置信号量资源
    int _p_step;
    // 消费者
    Sem _data_sem; // 数据信号量资源
    int _c_step;
    // 维护多生产，多消费, 2把锁
    Mutex _p_mutex;
    Mutex _c_mutex;
};
